package xyz.zyt123.hikvideo.config;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import xyz.zyt123.hikvideo.bean.Device;
import xyz.zyt123.hikvideo.bean.User;
import xyz.zyt123.hikvideo.demo.HCNetSDK;
import xyz.zyt123.hikvideo.service.DeviceService;
import xyz.zyt123.hikvideo.service.VideoService;
import xyz.zyt123.hikvideo.util.CacheUtil;
import xyz.zyt123.hikvideo.util.OsSelect;
import xyz.zyt123.hikvideo.util.VideoMgr;
import xyz.zyt123.hikvideo.util.VideoThread;

import java.util.List;

/**
 * @author zhuyuntao
 */
@Component
public class HikSdkConfig {

  @Autowired
  private DeviceService deviceService;

  @Autowired
  private VideoService videoService;

  @Autowired
  private VideoConfig videoConfig;

  private static final Logger log = LoggerFactory.getLogger(HikSdkConfig.class);
  public static HCNetSDK hCNetSDK = null;
  public static PlayCtrl playControl = null;

  @PreDestroy
  public void destroy() {
    log.info("SDK反初始化");
    // SDK反初始化，释放资源，只需要退出时调用一次
    hCNetSDK.NET_DVR_Cleanup();
  }

  /**
   * 动态库加载
   */
  private static void createSDKInstance() {
    if (hCNetSDK == null) {
      synchronized (HCNetSDK.class) {
        String strDllPath = "";
        try {
          if (OsSelect.isWindows()) {

            // win系统加载库路径
            strDllPath = System.getProperty("user.dir") + "\\lib\\HCNetSDK.dll";
          } else if (OsSelect.isLinux()) {
            // Linux系统加载库路径
            strDllPath = System.getProperty("user.dir") + "/lib/libhcnetsdk.so";
          }
          // strDllPath = "/opt/alarm/lib/libhcnetsdk.so";
          hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
        } catch (Exception ex) {
          System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
        }
      }
    }
  }

  /**
   * 播放库加载
   */
  private static void createPlayInstance() {
    if (playControl == null) {
      synchronized (PlayCtrl.class) {
        String strPlayPath = "";
        try {
          if (OsSelect.isWindows()) {
            // win系统加载库路径
            strPlayPath = System.getProperty("user.dir") + "\\lib\\PlayCtrl.dll";
          } else if (OsSelect.isLinux()) {
            // Linux系统加载库路径
            strPlayPath = System.getProperty("user.dir") + "/lib/libPlayCtrl.so";
          }
          //  strPlayPath = "/opt/alarm/lib/libPlayCtrl.so";
          playControl = (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);

        } catch (Exception ex) {
          System.out.println("loadLibrary: " + strPlayPath + " Error: " + ex.getMessage());
        }
      }
    }
  }

  static class FExceptionCallBack_Imp implements HCNetSDK.FExceptionCallBack {
    public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) {
      System.out.println("异常事件类型:" + dwType);
    }
  }

  @PostConstruct
  public void init() {
    log.info("初始化SDK");
    createSDKInstance();
    createPlayInstance();
    //SDK初始化，一个程序只需要调用一次
    hCNetSDK.NET_DVR_Init();
    log.info("初始化成功");
    if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, new FExceptionCallBack_Imp(), null)) {
      return;
    }
    //启动SDK写日志
    hCNetSDK.NET_DVR_SetLogToFile(3, "./sdkLog", false);
    Thread startVideo = new Thread(() -> {
      // 启动回放录制
      List<Device> list = deviceService.list();
      list.forEach(device -> {
        if (device.getVideo() == 0) {
          return;
        }
        VideoMgr video = new VideoMgr(device.getIp(), "8000", device.getUsername(), device.getPassword(), videoConfig.getVideo(), -1, device);
        User user = new User();
        user.setId(-1);
        user.setNickname("system");
        VideoThread thread = new VideoThread(video, videoService, user, "自动录像");
        thread.start();
        CacheUtil.PLAY_BACK.put(device.getId(), thread);
      });
    });
    startVideo.start();
  }
}
